package model

import (
	"context"
	"demo/internal/errorx"
	"fmt"
	"strconv"

	// "strconv"
	"strings"

	"github.com/Masterminds/squirrel"
	// sq "github.com/Masterminds/squirrel"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"github.com/zeromicro/go-zero/core/stringx"
	"gorm.io/gorm"
	// "gorm.io/gorm/clause"
)

var _ ServeyClassifyModel = (*customServeyClassifyModel)(nil)

type (
	// ServeyClassifyModel is an interface to be customized, add more methods here,
	// and implement the added methods in customServeyClassifyModel.
	ServeyClassifyModel interface {
		serveyClassifyModel
		withSession(session sqlx.Session) ServeyClassifyModel
		FindOneByNameAndCreatorID(ctx context.Context,name string,creatorId int64)(*ServeyClassify,error)
		ListBuilder() squirrel.SelectBuilder
		RowBuilder() squirrel.SelectBuilder
		CountBuilder(field string) squirrel.SelectBuilder
		SumBuilder(field string) squirrel.SelectBuilder
		FindPageListByPage(ctx context.Context, id, creatorId ,page, pageSize int64,clfName string, builder squirrel.SelectBuilder, showDel bool, orderBy string) ([]*ServeyClassify, error)
		RowsUpdateNum(ctx context.Context,session sqlx.Session,updateType,updateNum int64,scIds []int64)error
		InsertGetId(ctx context.Context, session sqlx.Session, data *ServeyClassify) (int64, error)
	}

	customServeyClassifyModel struct {
		*defaultServeyClassifyModel
	}
)

var serveyClassifyInsertCol = stringx.Remove(serveyClassifyFieldNames,"id")

// NewServeyClassifyModel returns a model for the database table.
func NewServeyClassifyModel(conn sqlx.SqlConn,gormConn *gorm.DB) ServeyClassifyModel {
	return &customServeyClassifyModel{
		defaultServeyClassifyModel: newServeyClassifyModel(conn,gormConn),
	}
}

func (m *customServeyClassifyModel) withSession(session sqlx.Session) ServeyClassifyModel {
	return NewServeyClassifyModel(sqlx.NewSqlConnFromSession(session),m.gormConn)
}

func (m *customServeyClassifyModel)FindOneByNameAndCreatorID(ctx context.Context,name string,creatorId int64)(*ServeyClassify,error){
	query := fmt.Sprintf("select %s from %s where clf_name = $1 and creator_id = $2 limit 1",serveyClassifyRows,m.table)
	var resp ServeyClassify
	err := m.conn.QueryRowCtx(ctx,&resp,query,name,creatorId)
	switch err{
	case nil:
		return &resp,nil
	case sqlx.ErrNotFound:
		return nil,ErrNotFound
	default:
		return nil,err 
	}
}

// func (m *customServeyClassifyModel)FindOneByIdAndCreateorID(ctx context.Context,id int64,creatorId int64)(*ServeyClassify,error){
// 	query := fmt.Sprintf("select %s from %s where id = $1 and creator_id = $2 limit 1",serveyClassifyRows,m.table)
// 	var resp ServeyClassify
// 	err := m.conn.QueryRowCtx(ctx,&resp,query,id,creatorId)
// 	switch err{
// 	case nil:
// 		return &resp,nil
// 	case sqlx.ErrNotFound:
// 		return nil,ErrNotFound
// 	default:
// 		return nil,err 
// 	}
// }

// updateType -> 0:+,1:-
func (m *customServeyClassifyModel) RowsUpdateNum(ctx context.Context,session sqlx.Session,updateType,updateNum int64,scIds []int64)error{
	
	strSlice := make([]string,len(scIds))
	for i,num := range scIds {
		strSlice[i] = fmt.Sprintf("%d",num)
	}
	query := fmt.Sprintf("update public.servey_classify set servey_num = servey_num")
	if updateType == 0 {
		query = query + "+" + strconv.FormatInt(int64(updateNum),10)
	}else {
		query = query + "-" + strconv.FormatInt(int64(updateNum),10)
	}
	query += " where id in ("
	for index,_ := range scIds {
		now := strconv.FormatInt(int64(index+1),10)
		query = query + "$" + now + ","
	}
	query,err := stringx.Substr(query,0,len(query) - 1)
	if err != nil {
		return errorx.NewBizError(500,"SQL语句拼接错误")
	}
	query = query + ")"
	var values []interface{} = make([]interface{}, 0)
	for _,val := range scIds{
		values = append(values, val)
	}
	if session != nil {
		_,err := session.ExecCtx(ctx,query,values...)
		if err != nil {
			fmt.Println(err)
		}
		return err
	}else{
		_,err := m.conn.ExecCtx(ctx,query,values...)
		return err
	}
}

func (m *customServeyClassifyModel) FindPageListByPage(ctx context.Context, id, creatorId ,page, pageSize int64,clfName string, builder squirrel.SelectBuilder, showDel bool, orderBy string) ([]*ServeyClassify, error) {

	// rb := builder
	// if id != 0 {
	// 	rb = rb.Where(sq.Eq{"id": id})
	// }	
	// if len(strings.TrimSpace(clfName)) != 0 {
	// 	rb = rb.Where(sq.ILike{"clf_name": "%"+clfName + "%"})
	// }
	// if creatorId != 0 {
	// 	rb = rb.Where(sq.Eq{"creator_id": creatorId})
	// }
	// rb = rb.OrderBy(orderBy)
	// rb = rb.Offset(uint64(( page - 1 ) * pageSize ))
	// rb = rb.Limit(uint64( pageSize ))

	db := m.gormConn.Table(m.table).Select("*")
	if id != 0 {
		db = db.Where(&ServeyClassify{Id: id})
	}	
	if len(strings.TrimSpace(clfName)) != 0 {
		db = db.Where("clf_name like ?","%"+clfName + "%")
	}
	if creatorId != 0 {
		db = db.Where(&ServeyClassify{CreatorId: creatorId},"CreatorId")
	}
	// db.Update("id",gorm.Expr("id + ?",1)).Clauses(clause.Returning{Columns: []clause.Column{{Name: "id"},{Name: "name"}}})
	// db.Order("id desc")
	// db.Model(&User{}).Select("name, sum(age) as total").Where("name LIKE ?", "group%").Group("name").First(&result)
	// db.Table("users").Select("name", "age").Where("name = ?", "Antonio").Scan(&result)
	// db.Table("(?) as u", db.Model(&User{}).Select("name", "age")).Where("age = ?", 18).Find(&User{})
	// db.Where(User{Name: "non_existing"}).Attrs("age", 20).FirstOrInit(&user)
	// db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrInit(&user)
	// db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrCreate(&user)
	// query := db.Table("order").Select("MAX(order.finished_at) as latest").Joins("left join user user on order.user_id = user.id").Where("user.age > ?", 18).Group("order.user_id")
	// 每次批量处理 100 条
	// result := db.Where("processed = ?", false).FindInBatches(&results, 100, func(tx *gorm.DB, batch int) error {
	// for _, result := range results {
	  // 批量处理找到的记录
	// }
  
	// tx.Save(&results)
  
	// tx.RowsAffected // 本次批量操作影响的记录数
  
	// batch // Batch 1, 2, 3
  
	// 如果返回错误会终止后续批量操作
	// return nil
//   })
	db.Offset(int((page - 1) * pageSize))
	db.Limit(int(pageSize))
	var resp []*ServeyClassify
	db.Find(&resp)
	// query,values,err := rb.ToSql()
	// if err != nil {
	// 	return nil,errorx.NewBizError(500,"sql语句生成错误")
	// }
	// err = m.conn.QueryRowsPartialCtx(ctx,&resp,query,values...)
	// switch err {
	// case nil:
	// 	return resp,nil
	// default:
	// 	fmt.Println("这里报错啦",err)
	// 	return nil,err
	// }
	return resp,nil
}

func (m *customServeyClassifyModel)InsertGetId(ctx context.Context, session sqlx.Session, data *ServeyClassify) (int64, error){
	query, args, err := m.InsertBuilder().Columns(serveyClassifyInsertCol...).
		Values(data.ClfName,data.ClfDesc,data.ServeyNum,data.CreatorId).
		Suffix("RETURNING \"id\"").
		ToSql()
	if err != nil {
		return 0, err
	}
	var id int64
	if session != nil {
		err = session.QueryRowPartialCtx(ctx, &id, query, args...)
	} else {
		err = m.conn.QueryRowPartialCtx(ctx, &id, query, args...)
	}
	if err != nil {
		return 0, err
	}

	return id, nil
}

func (m *customServeyClassifyModel)RowsQuery(ctx context.Context,builder squirrel.SelectBuilder,ids []int64){

}

func (m *customServeyClassifyModel) RowBuilder() squirrel.SelectBuilder {
	return squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar).Select(serveyClassifyRows).From(m.table)
}

func (m *customServeyClassifyModel) ListBuilder() squirrel.SelectBuilder {
	return squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar).Select("servey_classify.*").From(m.table)
}

func (m *customServeyClassifyModel) CountBuilder(field string) squirrel.SelectBuilder {
	return squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar).Select("COUNT(" + field + ")").From(m.table)
}
func (m *customServeyClassifyModel) SumBuilder(field string) squirrel.SelectBuilder {
	return squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar).Select("IFNULL(SUM(" + field + "),0)").From(m.table)
}

func (m *customServeyClassifyModel) InsertBuilder() squirrel.InsertBuilder {
	return squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar).Insert(m.table)
}

func (m *customServeyClassifyModel) UpdateBuilder() squirrel.UpdateBuilder {
	return squirrel.StatementBuilder.PlaceholderFormat(squirrel.Dollar).Update(m.table)
}